<?php

class XMLRPCSystemController extends XMLRPCController {
	
	/**
	 * @return array
	 */
	public function listMethods() {
		
		$methods = array();
		$dispatch_map = $this->action()->dispatchMap();
		foreach ($dispatch_map as $namespace => $controller_label) {
			@list($application_name, $controller_name) = explode('.', $controller_label);
			if (is_null($application_name) || is_null($controller_name))
				continue;
				
			if (!class_exists($controller_name) || !is_subclass_of($controller_name, 'Controller')) {
				$controller_class = str_classify($controller_name) . 'Controller';			
				if (!$this->loadControllerFile($application_name, $controller_name))
					continue;
			}
			
			if (!class_exists($controller_class))
				continue;
		
			$controller = new ReflectionAnnotatedClass($controller_class);
			$controller_methods = $controller->getMethods(ReflectionMethod::IS_PUBLIC);
			foreach ($controller_methods as $method)
				if (!$method->hasAnnotation('Concealed') && !$method->isConstructor() && !$method->isStatic())
					$methods[] = "{$namespace}.{$method->getName()}";
		}
		return $methods;
	}
	
	/**
	 * Returns the signature of the specified method. 
	 * @param string $method_name
	 * @return array
	 */
	public function methodSignature($method_name) {
		list($namespace, $method) = explode('.', $method_name);
		$dispatch_map = $this->action()->dispatchMap();
		
		$controller_label = $dispatch_map[$namespace];
		list($application_name, $controller_name) = explode('.', $controller_label);
		if (!class_exists($controller_name) || !is_subclass_of($controller_name, 'Controller')) {
			$controller_class = str_classify($controller_name) . 'Controller';			
			if (!$this->loadControllerFile($application_name, $controller_name))
				continue;
		}
		if (!class_exists($controller_class))
			throw new Exception('bah.');
		
		$controller = new ReflectionAnnotatedClass($controller_class);
		$method = $controller->getMethod($method);
		$signature_annotation = new SignatureAnnotation($method);
		
		$signatures = array();
		$return_types = $signature_annotation->returnTypes();

		foreach ($return_types as $type) {
			foreach ($signature_annotation->signatures() as $parameters) {
				$parameters = array_values($parameters);
				array_unshift($parameters, $type);
				$signatures[] = $parameters;
			}
		}
		return $signatures;
	}
	
	/**
	 * @param string $method_name
	 * @return string
	 */
	public function methodHelp($method_name) {
		list($namespace, $method) = explode('.', $method_name);
		$dispatch_map = $this->action()->dispatchMap();
		
		$controller_label = $dispatch_map[$namespace];
		list($application_name, $controller_name) = explode('.', $controller_label);
		if (!class_exists($controller_name) || !is_subclass_of($controller_name, 'Controller')) {
			$controller_class = str_classify($controller_name) . 'Controller';			
			if (!$this->loadControllerFile($application_name, $controller_name))
				continue;
		}
		if (!class_exists($controller_class))
			throw new Exception('bah.');
		
		$controller = new ReflectionAnnotatedClass($controller_class);
		$method = $controller->getMethod($method);
		$signature_annotation = new SignatureAnnotation($method);
		
		return $signature_annotation->documentation();
	}
	
	
	
	private function loadControllerFile($application_name, $controller_label) {
	
		foreach (Cobweb::get('APPLICATIONS_PATH') as $path) {
			$file = "{$path}/{$application_name}/controllers" .
			        "/{$controller_label}.controller.php";
			if (file_exists($file)) {
				require_once($file);
				return true;
			}
		}
		
		return false;
	}
	
}